Ext.apply(Ext.form.VTypes, {
    daterange : function(val, field) {
        var date = field.parseDate(val);

        if(!date){
            return false;
        }
        if (field.startDateField) {
            var start = Ext.getCmp(field.startDateField);
            if (!start.maxValue || (date.getTime() != start.maxValue.getTime())) {
                start.setMaxValue(date);
                start.validate();
            }
        }
        else if (field.endDateField) {
            var end = Ext.getCmp(field.endDateField);
            if (!end.minValue || (date.getTime() != end.minValue.getTime())) {
                end.setMinValue(date);
                end.validate();
            }
        }

        return true;
    }
});

(function(){

    var ns = Ext.ns('Ext.ux.plugins');
    /**
     * @class Ext.ux.plugins.DefaultButton
     * @extends Object
     *
     * Plugin for Button that will click() the button if the user presses ENTER while
     * a component in the button's form has focus.
     *
     * @author Stephen Friedrich
     * @date 21-JAN-2010
     * @version 0.2
     *
     */
    Ext.ux.plugins.DefaultButton =  Ext.extend(Object, {
        init: function(button) {
            button.on('afterRender', setupKeyListener, button);
        }
    });

    function setupKeyListener() {
        var formPanel = this.findParentByType('form');
        //noinspection ObjectAllocationIgnored
        new Ext.KeyMap(formPanel.el, {
            key: Ext.EventObject.ENTER,
            shift: false,
            alt: false,
            fn: function(keyCode, e){
                if(this.hidden || e.target.type === 'textarea' && !e.ctrlKey) {
                    return true;
                }

                this.el.select('button').item(0).dom.click();
                return false;
            },
            scope: this
        });
    }

    Ext.ComponentMgr.registerPlugin('defaultButton', ns.DefaultButton);

})();

function makeAuthForm(loginType, onSuccess) {
    var authForm = new Ext.FormPanel({
        url: '/json/login/',
        padding: 5,
        items: [{
            xtype: 'textfield',
            id: 'login',
            fieldLabel: 'Логин',
            allowBlank: false,
            listeners: {
                afterrender: function() {
                    this.focus(true, 500);
                }
            }
        },{
            xtype: 'textfield',
            id: 'password',
            fieldLabel: 'Пароль',
            inputType: 'password',
            allowBlank: false
        },{
            xtype: 'hidden',
            id: 'type',
            value: loginType
        }],
        buttons: [{
            text: 'Войти',
            id: 'submit',
            plugins: 'defaultButton',
            handler: function() {
                var form = authForm.getForm();
                if(form.isValid()) {
                    form.submit({
                        waitMsg: 'Производится попытка входа в систему',
                        success: function(form, action) {
                            onSuccess(form, action);
                        },
                        failure: function(form, action) {
                            Ext.Msg.show({
                                title: 'Ошибка при входе в систему',
                                msg: action.result.error_message,
                                buttons: Ext.MessageBox.OK,
                                icon: Ext.MessageBox.WARNING
                            });
                        }
                    });
                } else {
                    Ext.Msg.show({
                        title: 'Ошибка при валидации',
                        msg: 'В форму внесены некорректные данные',
                        buttons: Ext.MessageBox.OK,
                        icon: Ext.MessageBox.WARNING
                    });
                }
            }
        }]
    });
    var authFormWindow = new Ext.Window({
        title: 'Вход в систему',
        closable: false,
        modal: true,
        width: 262,
        items: [
            authForm
        ]
    });

    return authFormWindow;
}

function makeListenersGridWindow(chairId) {
    var listenersStore = new Ext.data.Store({
        autoLoad: true,
        reader: new Ext.data.JsonReader({
            fields: [
                'id',
                'surname',
                'name',
                'patronymic',
                'group',
                'phone',
                'hours'
            ],
            root: 'listeners'
        }),
        proxy: new Ext.data.HttpProxy({
            url: '/json/getlistenersforgrid/'
        })
    });

    var listenersGrid = new Ext.grid.GridPanel({
        store: listenersStore,
        anchor: '100%, 100%',
        height: 400,
        loadMask: true,
//        sm: new Ext.grid.RowSelectionModel({singleSelect:true}),
        columns: [
            {header: 'Фамилия', dataIndex: 'surname', sortable: true},
            {header: 'Имя', dataIndex: 'name', sortable: true},
            {header: 'Отчество', dataIndex: 'patronymic', sortable: true},
            {header: 'Группа', dataIndex: 'group', sortable: true},
            {header: 'Телефон', dataIndex: 'phone', sortable: true},
            {header: 'Оплаченные часы', dataIndex: 'hours', sortable: true},
            {
                xtype: 'actioncolumn',
                width: 40,
                header: 'Операции',
                items: [{
                    icon: '/images/icons/edit.gif',
                    tooltip: 'Редактировать',
                    handler: function(gridObj, rowIndex, colIndex) {
                        var rec = gridObj.getStore().getAt(rowIndex);
                        var listenerAttributes = makeListenerAttributesWindow(rec.data.id, 'Редактирование слушателя', listenersStore);
                        listenerAttributes.show();
                    }
                },{
                    icon: '/images/icons/delete.gif',
                    tooltip: 'Удалить',
                    handler: function(gridObj, rowIndex, colIndex) {
                        var rec = gridObj.getStore().getAt(rowIndex);
                        Ext.Msg.confirm('Удаление слушателя', 'Удалить слушателя ' + rec.data.surname + ' ' + rec.data.name + ' ' + rec.data.patronymic + '?', function(btn){
                            if(btn == 'yes') {
                                Ext.Ajax.request({
                                    url: '/json/deletelistener/',
                                    method: 'POST',
                                    params: {lid: rec.data.id},
                                    success: function(response, opts) {
                                        listenersStore.load();
                                    },
                                    failure: function(response, opts) {
                                        Ext.Msg.show({
                                            title: 'Ошибка при удалении',
                                            msg: 'Не удалось удалить слушателя',
                                            buttons: Ext.MessageBox.OK,
                                            icon: Ext.MessageBox.ERROR
                                        });
                                    }
                                });
                            }
                        });
                    }
                }]
            }
        ]
    });
    listenersGrid.on('rowdblclick', function(gridObj, rowIndex, e) {
        var rec = gridObj.getStore().getAt(rowIndex);
        var listenerDetails = makeListenerDetailsWindow(rec.data.id);
        listenerDetails.show();
    });

    return new Ext.Window({
        title: 'Список слушателей',
        modal: true,
        layout: 'anchor',
        width: 800,
        items: [
            listenersGrid
        ],
        buttons: [{
            text: 'Добавить нового слушателя',
            handler: function() {
                var listenerAttributes = makeListenerAttributesWindow(0, 'Добавление нового слушателя', listenersStore);
                listenerAttributes.show();
            }
        },{
            text: 'Печать',
            handler: function() {
                var selectedRows = listenersGrid.getSelectionModel().getSelections();
                var ids = new Array();
                Ext.each(selectedRows, function(item, index, allItems) {
                    ids.push(item.data.id);
                });
                if(ids.length > 0) {
                    location.href = '/print/printlistenerslist/?ids=' + ids.join();
                } else {
                    Ext.Msg.show({
                        title: 'Печать слушателей',
                        msg: 'Слушатели не выбраны. Для печати необходимо сперва выбрать нужных вам слушателей (при помощи мыши и клавиши "Ctrl" или "Shift"), и потом нажать кнопку "Печать"',
                        buttons: Ext.MessageBox.OK,
                        icon: Ext.MessageBox.WARNING
                    });
                }
            }
        }]
    });
}

function makeListenerAttributesWindow(listenerId, windowTitle, gridStore) {
    var listenerIdField = new Ext.form.Hidden({
        id: 'listener-id',
        name: 'id',
        value: listenerId
    });
    var surnameField = new Ext.form.TextField({
        id: 'surname',
        fieldLabel: 'Фамилия',
        anchor: '100%',
        allowBlank: false
    });
    var nameField = new Ext.form.TextField({
        id: 'name',
        fieldLabel: 'Имя',
        anchor: '100%',
        allowBlank: false
    });
    var patronymicField = new Ext.form.TextField({
        id: 'patronymic',
        fieldLabel: 'Отчество',
        anchor: '100%',
        allowBlank: false
    });
    var groupField = new Ext.form.TextField({
        id: 'group',
        fieldLabel: 'Группа',
        anchor: '100%'
    });
    var phoneField = new Ext.form.TextField({
        id: 'phone',
        fieldLabel: 'Контактный телефон',
        anchor: '100%'
    });
    var addressField = new Ext.form.TextField({
        id: 'address',
        fieldLabel: 'Адрес',
        anchor: '100%'
    });
    var passportSeriesField = new Ext.form.TextField({
        id: 'passport_series',
        fieldLabel: 'Серия паспорта',
//        anchor: '100%',
        width: '40px',
        allowBlank: false
    });
    var passportNumberField = new Ext.form.TextField({
        id: 'passport_number',
        fieldLabel: 'Номер паспорта',
//        anchor: '100%',
        width: '50px',
        allowBlank: false
    });
    var passportGivenout = new Ext.form.TextField({
        id: 'passport_givenout',
        fieldLabel: 'Кем выдан паспорт',
        anchor: '100%',
        allowBlank: false
    });
    var passportGivenoutWhen = new Ext.form.DateField({
        id: 'passport_givenout_when',
        fieldLabel: 'Когда выдан паспорт',
        format: 'Y-m-d',
        value: new Date(),
        anchor: '100%',
        allowBlank: false
    });
    var emailField = new Ext.form.TextField({
        id: 'email',
        fieldLabel: 'E-mail',
        anchor: '100%'
    });
    var additionalInfo = new Ext.form.TextArea({
        id: 'additional_info',
        fieldLabel: 'Дополнительно',
        anchor: '100%',
        height: 150
    });

    var attributesForm = new Ext.form.FormPanel({
        id: 'listener-attributes',
        padding: 5,
        url: '/json/savelistenerdata/',
        items: [
            listenerIdField,
            surnameField,
            nameField,
            patronymicField,
            groupField,
            phoneField,
            addressField,
            passportSeriesField,
            passportNumberField,
            passportGivenout,
            passportGivenoutWhen,
            emailField,
            additionalInfo
        ],
        buttons: [{
            text: 'Сохранить',
            plugins: 'defaultButton',
            handler: function() {
                var form = attributesForm.getForm();
                if (form.isValid()) {
                    form.submit({
                        waitMsg: 'Сохранение данных о слушателе',
                        success: function(form, action) {
                            if (gridStore != null) {
                                gridStore.load();
                            }
                            listenerAttributes.close();
                        },
                        failure: function(form, action) {
                            Ext.Msg.show({
                                title: 'Ошибка при сохранении',
                                msg: action.result.error_message,
                                buttons: Ext.MessageBox.OK,
                                icon: Ext.MessageBox.WARNING
                            });
                        }
                    })
                } else {
                    Ext.Msg.show({
                        title: 'Ошибка при валидации',
                        msg: 'В форму внесены некорректные данные',
                        buttons: Ext.MessageBox.OK,
                        icon: Ext.MessageBox.WARNING
                    });
                }
            }
        },{
            text: 'Отмена',
            handler: function() {
                listenerAttributes.close();
            }
        }]
    });

    var attributesStore = new Ext.data.Store({
        reader: new Ext.data.JsonReader({
            fields: [
                'surname',
                'name',
                'patronymic',
                'group',
                'phone',
                'address',
                'passport_series',
                'passport_number',
                'passport_givenout',
                'passport_givenout_when',
                'email',
                'additional_info'
            ],
            root: 'listenerdata'
        }),
        proxy: new Ext.data.HttpProxy({
            url: '/json/getlistenerdata/?lid=' + listenerId
        }),
        listeners: {
            'load': function() {
                var rec = this.getAt(0);
                surnameField.setValue(rec.data.surname);
                nameField.setValue(rec.data.name);
                patronymicField.setValue(rec.data.patronymic);
                groupField.setValue(rec.data.group);
                phoneField.setValue(rec.data.phone);
                addressField.setValue(rec.data.address);
                passportSeriesField.setValue(rec.data.passport_series);
                passportNumberField.setValue(rec.data.passport_number);
                passportGivenout.setValue(rec.data.passport_givenout);
                passportGivenoutWhen.setValue(rec.data.passport_givenout_when);
                emailField.setValue(rec.data.email);
                additionalInfo.setValue(rec.data.additional_info);
            }
        }
    });

    var listenerAttributes = new Ext.Window({
        title: windowTitle,
        modal: true,
        width: 483,
        items: [
            attributesForm
        ]
    });

    if(listenerId != 0) {
        listenerAttributes.on('show', function(){
            attributesStore.load();
        });
    }

    return listenerAttributes;
}

function makeListenerDetailsWindow(listenerId) {
    var personalDataPanel = new Ext.Panel({
        layout: 'table',
        defaults: {
            bodyStyle: 'padding: 5px'
        },
        layoutConfig: {
            columns: 2
        },
        border: false
    });

    var listenerPersonalDataStore = new Ext.data.Store({
        autoLoad: true,
        reader: new Ext.data.JsonReader({
            fields: [
                'id',
                'surname',
                'name',
                'patronymic',
                'group',
                'phone',
                'address',
                'passport_series',
                'passport_number',
                'passport_givenout',
                'passport_givenout_when',
                'email',
                'additional_info'
            ],
            root: 'listenerdata'
        }),
        proxy: new Ext.data.HttpProxy({
            url: '/json/getlistenerdata/?lid=' + listenerId
        }),
        listeners: {
            'load': function() {
                var rec = this.getAt(0);
                personalDataPanel.add({html: 'ФИО', width: 150});
                personalDataPanel.add({html: rec.data.surname + ' ' + rec.data.name + ' ' + rec.data.patronymic});
                personalDataPanel.add({html: 'Группа'});
                personalDataPanel.add({html: rec.data.group});
                personalDataPanel.add({html: 'Контактный телефон'});
                personalDataPanel.add({html: rec.data.phone});
                personalDataPanel.add({html: 'Адрес'});
                personalDataPanel.add({html: rec.data.address});
                personalDataPanel.add({html: 'Серия и номер паспорта'});
                personalDataPanel.add({html: rec.data.passport_series + ' ' + rec.data.passport_number});
                personalDataPanel.add({html: 'Кем выдан паспорт'});
                personalDataPanel.add({html: rec.data.passport_givenout});
                personalDataPanel.add({html: 'Когда выдан паспорт'});
                personalDataPanel.add({html: rec.data.passport_givenout_when});
                personalDataPanel.add({html: 'E-mail'});
                personalDataPanel.add({html: rec.data.email});
                personalDataPanel.add({html: 'Дополнительно'});
                personalDataPanel.add({html: Ext.util.Format.nl2br(Ext.util.Format.htmlEncode(rec.data.additional_info))});
                personalDataPanel.doLayout();
            }
        }
    });

    var listenerContractsStore = new Ext.data.Store({
        autoLoad: true,
        reader: new Ext.data.JsonReader({
            fields: [
                'id',
                'date',
                'hours',
                'total',
                'receipt_number',
                'paid'
            ],
            root: 'contracts'
        }),
        proxy: new Ext.data.HttpProxy({
            url: '/json/getlistenercontracts/?lid=' + listenerId
        })
    });

    var listenerPresenceStore = new Ext.data.Store({
        autoLoad: true,
        reader: new Ext.data.JsonReader({
            fields: [
                'id',
                'start',
                'theme',
                'surname',
                'name',
                'patronymic',
                'presented'
            ],
            root: 'presences'
        }),
        proxy: new Ext.data.HttpProxy({
            url: '/json/getlistenerpresence/?lid=' + listenerId
        })
    });

    return new Ext.Window({
        title: 'Детальная информация о слушателе',
        modal: true,
        width: 600,
        items: [{
            xtype: 'tabpanel',
            activeTab: 0,
            height: 300,
            items: [{
                title: 'Личные данные',
                autoScroll: true,
                items: [personalDataPanel]
            },{
                title: 'Договоры',
                layout: 'fit',
                items: [
                    new Ext.grid.GridPanel({
                        loadMask: true,
                        sm: new Ext.grid.RowSelectionModel({singleSelect:true}),
                        store: listenerContractsStore,
                        columns: [
                            {header: 'Оплачено', dataIndex: 'paid', sortable: true, width: 30, renderer: function(value) {
                                    return (value == 0) ? 'Нет' : 'Да';
                            }},
                            {header: '№ договора', dataIndex: 'id', sortable: true},
                            {header: 'Дата оформления', dataIndex: 'date', sortable: true},
                            {header: 'Количество часов', dataIndex: 'hours', sortable: true},
                            {header: 'Сумма', dataIndex: 'total', sortable: true},
                            {header: '№ квитанции', dataIndex: 'receipt_number', sortable: true}
                        ]
                    })
                ]
            },{
                title: 'Посещаемость',
                layout: 'fit',
                items: [
                    new Ext.grid.GridPanel({
                        loadMask: true,
                        sm: new Ext.grid.RowSelectionModel({singleSelect:true}),
                        store: listenerPresenceStore,
                        columns: [
                            {header: 'Дата занятия', dataIndex: 'start', sortable: true, width: 120},
                            {header: 'Тема', dataIndex: 'theme', sortable: true, width: 200},
                            {header: 'Преподаватель', dataIndex: 'teacher', sortable: true, width: 200, renderer: function(value, metadata, record, rowIndex, colIndex, store) {
                                    return record.get('surname') + ' ' + record.get('name') + ' ' + record.get('patronymic');
                            }},
                            {header: 'Присутствовал', dataIndex: 'presented', sortable: true, width: 50, renderer: function(value){return (value == true) ? 'Да' : 'Нет'}}
                        ]
                    })
                ]
            }]
        }]
    });
}

function makeListenerSelectWindow(chairId, listenerField, listenerIdField) {
    var listenersStore = new Ext.data.Store({
        autoLoad: true,
        reader: new Ext.data.JsonReader({
            fields: [
                'id',
                'surname',
                'name',
                'patronymic',
                'group',
                'phone',
                'passport_number',
                'hours'
            ],
            root: 'listeners'
        }),
        proxy: new Ext.data.HttpProxy({
            url: '/json/getlistenersforgrid/'
        })
    });

    var listenersGrid = new Ext.grid.GridPanel({
        store: listenersStore,
        anchor: '100%, 100%',
        height: 400,
        loadMask: true,
        sm: new Ext.grid.RowSelectionModel({singleSelect:true}),
        columns: [
            {header: 'Фамилия', dataIndex: 'surname', sortable: true},
            {header: 'Имя', dataIndex: 'name', sortable: true},
            {header: 'Отчество', dataIndex: 'patronymic', sortable: true},
            {header: 'Группа', dataIndex: 'group', sortable: true},
            {header: 'Телефон', dataIndex: 'phone', sortable: true},
            {header: 'Оплаченные часы', dataIndex: 'hours', sortable: true}
        ]
    });
    listenersGrid.on('rowdblclick', function(gridObj, rowIndex, e) {
        var rec = gridObj.getStore().getAt(rowIndex);
        listenerField.setValue(rec.data.surname + ' ' + rec.data.name + ' ' + rec.data.patronymic + ' - ' + rec.data.passport_number + ' - ' + rec.data.group);
        listenerIdField.setValue(rec.data.id);
        listenerSelectWnd.close();
    });

    var listenerSelectWnd =  new Ext.Window({
        title: 'Выбор слушателя',
        modal: true,
        layout: 'anchor',
        width: 800,
        items: [
            listenersGrid
        ],
        buttons: [{
            text: 'Добавить нового слушателя',
            handler: function() {
                var listenerAttributes = makeListenerAttributesWindow(0, 'Добавление нового слушателя', listenersStore);
                listenerAttributes.show();
            }
        },{
            text: 'Выбрать',
            handler: function() {
                var rec = listenersGrid.getSelectionModel().getSelected();
                listenerField.setValue(rec.data.surname + ' ' + rec.data.name + ' ' + rec.data.patronymic + ' - ' + rec.data.passport_number + ' - ' + rec.data.group);
                listenerIdField.setValue(rec.data.id);
                listenerSelectWnd.close();
            }
        }]
    });

    return listenerSelectWnd;
}

function makeContractsGridWindow(chairId) {
    var contractsStore = new Ext.data.Store({
        autoLoad: true,
        reader: new Ext.data.JsonReader({
            fields: [
                'id',
                'date',
                'listener',
                'start',
                'end',
                'total',
                'receipt_total',
                'receipt_number',
                'receipt_date',
                'paid'
            ],
            root: 'contracts'
        }),
        proxy: new Ext.data.HttpProxy({
            url: '/json/getcontractsforgrid/?cid=' + chairId
        })
    });

    var contractsGrid = new Ext.grid.GridPanel({
        store: contractsStore,
        anchor: '100%, 100%',
        height: 400,
        loadMask: true,
        sm: new Ext.grid.RowSelectionModel({singleSelect:true}),
        columns: [
            {header: '№ договора', dataIndex: 'id', sortable: true, width: 60},
            {header: 'Дата оформления', dataIndex: 'date', sortable: true},
            {header: 'Слушатель', dataIndex: 'listener', sortable: true, width: 200},
            {header: 'Дата начала', dataIndex: 'start', sortable: true},
            {header: 'Дата окончания', dataIndex: 'end', sortable: true},
            {header: 'Сумма', dataIndex: 'total', sortable: true, width: 60},
            {
                header: 'Оплачено',
                dataIndex: 'paid',
                sortable: true,
                xtype: 'booleancolumn',
                trueText: 'Да',
                falseText: 'Нет',
                width: 30,
                listeners: {
                    'click': function(cellObj, gridObj, rowIndex) {
                        var rec = gridObj.getStore().getAt(rowIndex);
                        if(rec.data.paid == 1) {
                            Ext.Msg.confirm('Отмена оплаты договора', 'Отменить оплату договора №' + rec.data.id + ' оформленный на ' + rec.data.listener + '?', function(btn){
                                if(btn == 'yes') {
                                    Ext.Ajax.request({
                                        url: '/json/unpaycontract/',
                                        method: 'POST',
                                        params: {
                                            contract_id: rec.data.id
                                        },
                                        success: function() {
                                            contractsStore.load();
                                        }
                                    });
                                }
                            });
                        } else if(rec.data.paid == 0) {
                            var receiptAttributes = makeReceiptAttributesWindow(0, 'Добавление квитанции', rec.data.id, contractsStore);
                            receiptAttributes.show();
                        }
                    }
                }
            },
            {header: 'По квитанции', dataIndex: 'receipt_total', sortable: true, width: 60},
            {header: '№ квитанции', dataIndex: 'receipt_number', sortable: true},
            {header: 'Дата квитанции', dataIndex: 'receipt_date', sortable: true},
            {
                xtype: 'actioncolumn',
                width: 72,
                header: 'Операции',
                items: [{
                    icon: '/images/icons/copy.gif',
                    tooltip: 'Копировать',
                    handler: function(gridObj, rowIndex, colIndex) {
                        var rec = gridObj.getStore().getAt(rowIndex);
                        var contractAttributes = makeContractAttributesWindow(rec.data.id, chairId, 'Оформление нового договора', contractsStore, true);
                        contractAttributes.show();
                    }
                },{
                    icon: '/images/icons/edit.gif',
                    tooltip: 'Редактировать',
                    handler: function(gridObj, rowIndex, colIndex) {
                        var rec = gridObj.getStore().getAt(rowIndex);
                        var contractAttributes = makeContractAttributesWindow(rec.data.id, chairId, 'Редактирование договора №' + rec.data.id, contractsStore, false);
                        contractAttributes.show();
                    }
                },{
                    icon: '/images/icons/delete.gif',
                    tooltip: 'Удалить',
                    handler: function(gridObj, rowIndex, colIndex) {
                        var rec = gridObj.getStore().getAt(rowIndex);
                        Ext.Msg.confirm('Удаление договора', 'Удалить договор №' + rec.data.id + ' оформленный на ' + rec.data.listener + ' ?', function(btn){
                            if(btn == 'yes') {
                                Ext.Ajax.request({
                                    url: '/json/deletecontract/',
                                    method: 'POST',
                                    params: {cid: rec.data.id},
                                    success: function(response, opts) {
                                        contractsStore.load();
                                    },
                                    failure: function(response, opts) {
                                        Ext.Msg.show({
                                            title: 'Ошибка при удалении',
                                            msg: 'Не удалось удалить договор',
                                            buttons: Ext.MessageBox.OK,
                                            icon: Ext.MessageBox.ERROR
                                        });
                                    }
                                });
                            }
                        });
                    }
                },{
                    icon: '/images/icons/print.gif',
                    tooltip: 'Печать',
                    handler: function(gridObj, rowIndex, colIndex) {
                        var rec = gridObj.getStore().getAt(rowIndex);
                        printContract(rec.data.id);
                    }
                }]
            }
        ]
    });
    contractsGrid.on('rowdblclick', function(gridObj, rowIndex, e) {
        var rec = gridObj.getStore().getAt(rowIndex);
        var contractDetails = makeContractDetailsWindow(rec.data.id);
        contractDetails.show();
    });

    return new Ext.Window({
        title: 'Список договоров',
        modal: true,
        layout: 'anchor',
        width: 1020,
        items: [
            contractsGrid
        ],
        buttons: [{
            text: 'Оформить новый договор',
            handler: function() {
                var contractAttributes = makeContractAttributesWindow(0, chairId, 'Оформление нового договора', contractsStore, false);
                contractAttributes.show();
            }
        }]
    });
}

function makeContractAttributesWindow(contractId, chairId, windowTitle, gridStore, isCopy) {
    var contractIdField = new Ext.form.Hidden({
        id: 'contract-id',
        name: 'id',
        value: (isCopy ? 0 : contractId)
    });
    var chairIdField = new Ext.form.Hidden({
        id: 'chair_id',
        value: chairId
    });
    var dateField = new Ext.form.DateField({
        id: 'date',
        fieldLabel: 'Дата оформления',
        format: 'Y-m-d',
        value: new Date(),
        allowBlank: false,
        anchor: '100%'
    });
    var listenerIdField = new Ext.form.Hidden({
        id: 'listener_id',
        allowBlank: false
    });
    var listenerField = new Ext.form.TriggerField({
        id: 'listener',
        fieldLabel: 'Слушатель',
        editable: false,
        submitValue: false,
        allowBlank: false,
        anchor: '100%'
    });
    listenerField.onTriggerClick = function(ev) {
        var listenerSelect = makeListenerSelectWindow(chairId, this, listenerIdField);
        listenerSelect.show();
    }
    var startField = new Ext.form.DateField({
        id: 'start',
        fieldLabel: 'Дата начала обучения',
        format: 'Y-m-d',
        allowBlank: false,
        value: Ext.state.Manager.get('contractStartDate'),
        anchor: '100%',
        vtype: 'daterange',
        endDateField: 'end'
    });
    var endField = new Ext.form.DateField({
        id: 'end',
        fieldLabel: 'Дата окончания обучения',
        format: 'Y-m-d',
        allowBlank: false,
        value: Ext.state.Manager.get('contractEndDate'),
        anchor: '100%',
        vtype: 'daterange',
        startDateField: 'start'
    });
    var hoursField = new Ext.form.TextField({
        id: 'hours',
        fieldLabel: 'Количество академических часов',
        allowBlank: false,
        maskRe: /[0-9]/,
        anchor: '100%'
    });
    var totalField = new Ext.form.NumberField({
        id: 'total',
        fieldLabel: 'Сумма',
        minValue: 0,
        allowBlank: false,
        anchor: '100%'
    });
    var themesField = new Ext.form.TextArea({
        id: 'themes',
        fieldLabel: 'Желаемые темы',
        anchor: '100%',
        height: 150
    });

    var attributesForm = new Ext.form.FormPanel({
        id: 'contract-attributes',
        padding: 5,
        url: '/json/savecontractdata/',
        items: [
            contractIdField,
            chairIdField,
            dateField,
            listenerIdField,
            listenerField,
            startField,
            endField,
            hoursField,
            totalField,
            themesField
        ],
        buttons: [{
            text: 'Сохранить',
            plugins: 'defaultButton',
            handler: function() {
                var form = attributesForm.getForm();
                if (form.isValid()) {
                    form.submit({
                        waitMsg: 'Сохранение данных о договоре',
                        success: function(form, action) {
                            Ext.state.Manager.set('contractStartDate', startField.getValue());
                            Ext.state.Manager.set('contractEndDate', endField.getValue());
                            if (gridStore != null) {
                                gridStore.load();
                            }
                            if(contractId == 0) {
                                Ext.Msg.show({
                                    title: 'Оформление успешно завершено',
                                    msg: 'Договор добавлен в базу под №' + action.result.contractid,
                                    buttons: Ext.MessageBox.OK,
                                    icon: Ext.MessageBox.INFO
                                });
                            }
                            contractAttributes.close();
                        }
                    })
                } else {
                    Ext.Msg.show({
                        title: 'Ошибка при валидации',
                        msg: 'В форму внесены некорректные данные',
                        buttons: Ext.MessageBox.OK,
                        icon: Ext.MessageBox.WARNING
                    });
                }
            }
        },{
            text: 'Сохранить и распечатать',
            handler: function() {
                var form = attributesForm.getForm();
                if (form.isValid()) {
                    form.submit({
                        waitMsg: 'Сохранение данных о договоре',
                        success: function(form, action) {
                            Ext.state.Manager.set('contractStartDate', startField.getValue());
                            Ext.state.Manager.set('contractEndDate', endField.getValue());
                            if (gridStore != null) {
                                gridStore.load({
                                    callback: function() {
                                        contractAttributes.close();
                                        printContract(action.result.contractid);
                                    }
                                });
                            }
                            if(contractId == 0) {
                                Ext.Msg.show({
                                    title: 'Оформление успешно завершено',
                                    msg: 'Договор добавлен в базу под №' + action.result.contractid,
                                    buttons: Ext.MessageBox.OK,
                                    icon: Ext.MessageBox.INFO
                                });
                            }
                        }
                    })
                } else {
                    Ext.Msg.show({
                        title: 'Ошибка при валидации',
                        msg: 'В форму внесены некорректные данные',
                        buttons: Ext.MessageBox.OK,
                        icon: Ext.MessageBox.WARNING
                    });
                }
            }
        },{
            text: 'Отмена',
            handler: function() {
                contractAttributes.close();
            }
        }]
    });

    var attributesStore = new Ext.data.Store({
        reader: new Ext.data.JsonReader({
            fields: [
                'chair_id',
                'date',
                'listener_id',
                'listener',
                'listener_group',
                'listener_passport_number',
                'start',
                'end',
                'hours',
                'total',
                'themes'
            ],
            root: 'contractdata'
        }),
        proxy: new Ext.data.HttpProxy({
            url: '/json/getcontractdata/?cid=' + contractId
        }),
        listeners: {
            'load': function() {
                var rec = this.getAt(0);
                chairIdField.setValue(rec.data.chair_id);
                if (isCopy) dateField.setValue(new Date()); else dateField.setValue(rec.data.date);
                listenerIdField.setValue(rec.data.listener_id);
                listenerField.setValue(rec.data.listener + ' - ' + rec.data.listener_passport_number + ' - ' + rec.data.listener_group);
                startField.setValue(rec.data.start);
                endField.setValue(rec.data.end);
                hoursField.setValue(rec.data.hours);
                totalField.setValue(rec.data.total);
                themesField.setValue(rec.data.themes);
            }
        }
    });

    var contractAttributes = new Ext.Window({
        title: windowTitle,
        modal: true,
        width: 483,
        items: [
            attributesForm
        ]
    });

    if(contractId != 0) {
        contractAttributes.on('show', function(){
            attributesStore.load();
        });
    }

    return contractAttributes;
}

function makeContractDetailsWindow(contractId) {
    var contractDetailsPanel = new Ext.Panel({
        layout: 'table',
        defaults: {
            bodyStyle: 'padding: 5px'
        },
        layoutConfig: {
            columns: 2
        },
        border: false
    });

    var contractDetailsStore = new Ext.data.Store({
        autoLoad: true,
        reader: new Ext.data.JsonReader({
            fields: [
                'id',
                'date',
                'hours',
                'start',
                'end',
                'total',
                'themes',
                'paid',
                'receipt_number',
                'receipt_total',
                'receipt_date',
                'chair_name',
                'chair_abbreviation',
                'listener_surname',
                'listener_name',
                'listener_patronymic',
                'listener_group',
                'listener_phone',
                'listener_address',
                'listener_passport_series',
                'listener_passport_number',
                'listener_passport_givenout',
                'listener_passport_givenout_when',
                'listener_email'
            ],
            root: 'contractdetails'
        }),
        proxy: new Ext.data.HttpProxy({
            url: '/json/getcontractdetails/?cid=' + contractId
        }),
        listeners: {
            load: function() {
                var rec = this.getAt(0);
                contractDetailsPanel.add({html: 'Кафедра'});
                contractDetailsPanel.add({html: rec.data.chair_name});
                contractDetailsPanel.add({html: '№ договора'});
                contractDetailsPanel.add({html: rec.data.id.toString()});
                contractDetailsPanel.add({html: 'Дата оформления'});
                contractDetailsPanel.add({html: rec.data.date});
                contractDetailsPanel.add({html: 'Дата начала обучения'});
                contractDetailsPanel.add({html: rec.data.start});
                contractDetailsPanel.add({html: 'Дата окончания обучения'});
                contractDetailsPanel.add({html: rec.data.end});
                contractDetailsPanel.add({html: 'Сумма договора'});
                contractDetailsPanel.add({html: rec.data.total.toString()});
                contractDetailsPanel.add({html: 'Статус оплаты'});
                contractDetailsPanel.add({html: rec.data.paid ? 'Оплачено' : '<b>Не оплачено</b>'});
                contractDetailsPanel.add({html: 'ФИО слушателя'});
                contractDetailsPanel.add({html: rec.data.listener_surname + ' ' + rec.data.listener_name + ' ' + rec.data.listener_patronymic});
                contractDetailsPanel.add({html: 'Группа слушателя'});
                contractDetailsPanel.add({html: rec.data.listener_group});
                contractDetailsPanel.add({html: 'Контактный телефон'});
                contractDetailsPanel.add({html: rec.data.listener_phone});
                contractDetailsPanel.add({html: 'Адрес слушателя'});
                contractDetailsPanel.add({html: rec.data.listener_address});
                contractDetailsPanel.add({html: 'Серия и номер паспорта слушателя'});
                contractDetailsPanel.add({html: rec.data.listener_passport_series + ' ' + rec.data.listener_passport_number});
                contractDetailsPanel.add({html: 'Кем выдан паспорт'});
                contractDetailsPanel.add({html: rec.data.listener_passport_givenout});
                contractDetailsPanel.add({html: 'Когда выдан паспорт'});
                contractDetailsPanel.add({html: rec.data.listener_passport_givenout_when});
                contractDetailsPanel.add({html: 'Желаемые темы'});
                contractDetailsPanel.add({html: Ext.util.Format.nl2br(Ext.util.Format.htmlEncode(rec.data.themes))});
                contractDetailsPanel.doLayout();
            }
        }
    });

    var contractDetails = new Ext.Window({
        title: 'Детальная информация о договоре №' + contractId,
        modal: true,
        height: 500,
        width: 600,
        autoScroll: true,
        items: [ contractDetailsPanel ],
        buttons: [{
            text: 'Печать',
            handler: function() {
                printContract(contractId);
            }
        }]
    });

    return contractDetails;
}

function printContract(contractId) {
    location.href = '/print/printcontract?cid=' + contractId;
}

function makeReceiptAttributesWindow(receiptId, windowTitle, contractId , gridStore) {
    var contractIdField = new Ext.form.Hidden({
        id: 'contract_id',
        value: contractId
    });
    var numberField = new Ext.form.TextField({
        id: 'receipt_number',
        fieldLabel: '№ квитанции',
        allowBlank: false,
        anchor: '100%'
    });
    var totalField = new Ext.form.NumberField({
        id: 'receipt_total',
        fieldLabel: 'Сумма',
        allowBlank: false,
        anchor: '100%'
    });
    var dateField = new Ext.form.DateField({
        id: 'receipt_date',
        fieldLabel: 'Дата оплаты',
        format: 'Y-m-d',
        allowBlank: false,
        value: new Date(),
        anchor: '100%'
    });

    var attributesForm = new Ext.form.FormPanel({
        id: 'receipt-attributes',
        url: '/json/paycontract/',
        padding: 5,
        items: [
            numberField,
            totalField,
            dateField,
            contractIdField
        ],
        buttons: [{
            text: 'Сохранить',
            plugins: 'defaultButton',
            handler: function() {
                var form = attributesForm.getForm();
                if (form.isValid()) {
                    form.submit({
                        waitMsg: 'Сохранение данных о квитанции',
                        success: function(form, action) {
                            if (gridStore != null) {
                                gridStore.load();
                            }
                            receiptArributes.close();
                        }
                    })
                } else {
                    Ext.Msg.show({
                        title: 'Ошибка при валидации',
                        msg: 'В форму внесены некорректные данные',
                        buttons: Ext.MessageBox.OK,
                        icon: Ext.MessageBox.WARNING
                    });
                }
            }
        },{
            text: 'Отмена',
            handler: function() {
                receiptArributes.close();
            }
        }]
    });

    var attributesStore = new Ext.data.Store({
        reader: new Ext.data.JsonReader({
            fields: [
                'number',
                'total',
                'date'
            ],
            root: 'receiptdata'
        }),
        proxy: new Ext.data.HttpProxy({
            url: '/json/getreceiptdata/rid?=' + receiptId
        }),
        listeners: {
            'load': function() {
                var rec = this.getAt(0);
                numberField.setValue(rec.data.number);
                totalField.setValue(rec.data.total);
                dateField.setValue(rec.data.date);
            }
        }
    });

    var receiptArributes = new Ext.Window({
        title: windowTitle,
        modal: true,
        width: 483,
        items: [
            attributesForm
        ]
    });

    if(receiptId != 0) {
        receiptArributes.on('show',function() {
            attributesStore.load();
        });
    }

    return receiptArributes;
}

function makeIntensivesGridWindow(chairId) {
    var intensivesStore = new Ext.data.Store({
        autoLoad: true,
        reader: new Ext.data.JsonReader({
            fields: [
                'id',
                'name'
            ],
            root: 'intensives'
        }),
        proxy: new Ext.data.HttpProxy({
            url: '/json/getintensivesforgrid/?cid=' + chairId
        })
    });

    var intensivesGrid = new Ext.grid.GridPanel({
        store: intensivesStore,
        anchor: '100%, 100%',
        height: 400,
        loadMask: true,
        sm: new Ext.grid.RowSelectionModel({singleSelect:true}),
        columns: [
            {header: 'Наименование интенсива', dataIndex: 'name', sortable: true, width: 550},
            {
                xtype: 'actioncolumn',
                width: 40,
                header: 'Операции',
                items: [{
                    icon: '/images/icons/edit.gif',
                    tooltip: 'Редактировать',
                    handler: function(gridObj, rowIndex, colIndex) {
                        var rec = gridObj.getStore().getAt(rowIndex);
                        var intensiveAttributes = makeIntensiveAttributesWindow(rec.data.id, chairId, 'Редактирование интенсива', intensivesStore, false);
                        intensiveAttributes.show();
                    }
                },{
                    icon: '/images/icons/delete.gif',
                    tooltip: 'Удалить',
                    handler: function(gridObj, rowIndex, colIndex) {
                        var rec = gridObj.getStore().getAt(rowIndex);
                        Ext.Msg.confirm('Удаление интенсива', 'Удалить интенсив "' + rec.data.name + '" ?', function(btn){
                            if(btn == 'yes') {
                                Ext.Ajax.request({
                                    url: '/json/deleteintensive/',
                                    method: 'POST',
                                    params: {iid: rec.data.id},
                                    success: function(response, opts) {
                                        intensivesStore.load();
                                        refreshIntensivesToolbar(chairId);
                                    },
                                    failure: function(response, opts) {
                                        Ext.Msg.show({
                                            title: 'Ошибка при удалении',
                                            msg: 'Не удалось удалить интенсив',
                                            buttons: Ext.MessageBox.OK,
                                            icon: Ext.MessageBox.ERROR
                                        });
                                    }
                                });
                            }
                        });
                    }
                }]
            }
        ]
    });

    return new Ext.Window({
        title: 'Список интенсивов',
        modal: true,
        layout: 'anchor',
        width: 650,
        items: [
            intensivesGrid
        ],
        buttons: [{
            text: 'Добавить новый интенсив',
            handler: function() {
                var intensiveAttributes = makeIntensiveAttributesWindow(0, chairId, 'Добавление нового интенсива', intensivesStore, false);
                intensiveAttributes.show();
            }
        }]
    });
}

function makeIntensiveAttributesWindow(intensiveId, chairId, windowTitle, gridStore) {
    var intensiveIdField = new Ext.form.Hidden({
        id: 'intensive-id',
        name: 'id',
        value: intensiveId
    });
    var chairIdField = new Ext.form.Hidden({
        id: 'chair_id',
        value: chairId
    });
    var nameField = new Ext.form.TextField({
        id: 'name',
        fieldLabel: 'Наименование',
        allowBlank: false,
        anchor: '100%'
    });

    var attributesForm = new Ext.form.FormPanel({
        id: 'intensive-attributes',
        padding: 5,
        url: '/json/saveintensivedata/',
        items: [
            intensiveIdField,
            chairIdField,
            nameField
        ],
        buttons: [{
            text: 'Сохранить',
            plugins: 'defaultButton',
            handler: function() {
                var form = attributesForm.getForm();
                if (form.isValid()) {
                    form.submit({
                        waitMsg: 'Сохранение данных об интенсиве',
                        success: function(form, action) {
                            if (gridStore != null) {
                                gridStore.load();
                            }
                            refreshIntensivesToolbar(chairId);
                            intensiveAttributes.close();
                        }
                    })
                } else {
                    Ext.Msg.show({
                        title: 'Ошибка при валидации',
                        msg: 'В форму внесены некорректные данные',
                        buttons: Ext.MessageBox.OK,
                        icon: Ext.MessageBox.WARNING
                    });
                }
            }
        },{
            text: 'Отмена',
            handler: function() {
                intensiveAttributes.close();
            }
        }]
    });

    var attributesStore = new Ext.data.Store({
        reader: new Ext.data.JsonReader({
            fields: [
                'id',
                'name'
            ],
            root: 'intensivedata'
        }),
        proxy: new Ext.data.HttpProxy({
            url: '/json/getintensivedata/?iid=' + intensiveId
        }),
        listeners: {
            'load': function() {
                var rec = this.getAt(0);
                nameField.setValue(rec.data.name);
            }
        }
    });

    var intensiveAttributes = new Ext.Window({
        title: windowTitle,
        modal: true,
        width: 483,
        items: [
            attributesForm
        ]
    });

    if(intensiveId != 0) {
        intensiveAttributes.on('show', function(){
            attributesStore.load();
        });
    }

    return intensiveAttributes;
}

function makeTeachersGridWindow(chairId) {
    var teachersStore = new Ext.data.Store({
        autoLoad: true,
        reader: new Ext.data.JsonReader({
            fields: [
                'id',
                'surname',
                'name',
                'patronymic'
            ],
            root: 'teachers'
        }),
        proxy: new Ext.data.HttpProxy({
            url: '/json/getteachersforgrid/?cid=' + chairId
        })
    });

    var teachersGrid = new Ext.grid.GridPanel({
        store: teachersStore,
        anchor: '100%, 100%',
        height: 400,
        loadMask: true,
        sm: new Ext.grid.RowSelectionModel({singleSelect:true}),
        columns: [
            {header: 'Фамилия', dataIndex: 'surname', sortable: true, width: 200},
            {header: 'Имя', dataIndex: 'name', sortable: true, width: 200},
            {header: 'Отчество', dataIndex: 'patronymic', sortable: true, width: 200},
            {
                xtype: 'actioncolumn',
                width: 40,
                header: 'Операции',
                items: [{
                    icon: '/images/icons/edit.gif',
                    tooltip: 'Редактировать',
                    handler: function(gridObj, rowIndex, colIndex) {
                        var rec = gridObj.getStore().getAt(rowIndex);
                        var teacherAttributes = makeTeacherAttributesWindow(rec.data.id, chairId, 'Редактирование преподавателя', teachersStore, false);
                        teacherAttributes.show();
                    }
                },{
                    icon: '/images/icons/delete.gif',
                    tooltip: 'Удалить',
                    handler: function(gridObj, rowIndex, colIndex) {
                        var rec = gridObj.getStore().getAt(rowIndex);
                        Ext.Msg.confirm('Удаление преподавателя', 'Удалить преподавателя ' + rec.data.surname + ' ' + rec.data.name + ' ' + rec.data.patronymic + '?', function(btn){
                            if(btn == 'yes') {
                                Ext.Ajax.request({
                                    url: '/json/deleteteacher/',
                                    method: 'POST',
                                    params: {tid: rec.data.id},
                                    success: function(response, opts) {
                                        teachersStore.load();
                                    },
                                    failure: function(response, opts) {
                                        Ext.Msg.show({
                                            title: 'Ошибка при удалении',
                                            msg: 'Не удалось удалить преподавателя',
                                            buttons: Ext.MessageBox.OK,
                                            icon: Ext.MessageBox.ERROR
                                        });
                                    }
                                });
                            }
                        });
                    }
                }]
            }
        ],
        listeners: {
            'rowcontextmenu': function(gridObj, rowIndex, event) {
                event.stopEvent();
                var menu = new Ext.menu.Menu({
                    items: [{
                        text: 'Свободные часы преподавателя',
                        handler: function() {
                            var teacherData = teachersStore.getAt(rowIndex).data;
                            var scheduleWindow = makeTeacherScheduleWindow(teacherData);
                            scheduleWindow.show();
                        }
                    },{
                        text: 'Назначенные занятия',
                        handler: function() {
                            var teacherData = teachersStore.getAt(rowIndex).data;
                            var lessonsGridWindow = makeTeacherLessonGridWindow(teacherData);
                            lessonsGridWindow.show();
                        }
                    },'-',{
                        text: 'Сформировать трудовой договор на выполнение учебной работы',
                        handler: function() {
                            var teacherData = teachersStore.getAt(rowIndex).data;
                            var contractWindow = makeGenerateTeacherContractWindow(teacherData);
                            contractWindow.show();
                        }
                    },{
                        text: 'Сформировать отчёт о выполнении учебной работы',
                        handler: function() {
                            
                        }
                    }]
                });
                menu.showAt(Ext.EventObject.getXY());
            }
        }
    });

    return new Ext.Window({
        title: 'Список преподавателей',
        modal: true,
        layout: 'anchor',
        width: 660,
        items: [
            teachersGrid
        ],
        buttons: [{
            text: 'Добавить нового преподавателя',
            handler: function() {
                var teacherAttributes = makeTeacherAttributesWindow(0, chairId, 'Добавление нового преподавателя', teachersStore, false);
                teacherAttributes.show();
            }
        }]
    });
}

function makeTeacherScheduleWindow(teacherData) {
    var scheduleStore = new Ext.data.Store({
        autoLoad: true,
        reader: new Ext.data.JsonReader({
            fields: Ext.calendar.EventRecord.prototype.fields.getRange(),
            root: 'tasks'
        }),
        proxy: new Ext.data.HttpProxy({
            url: '/json/getteacherschedule/?tid=' + teacherData.id
        })
    });
    
    var scheduleCalendar = new Ext.calendar.CalendarPanel({
        id: 'teacher-schedule-calendar',
        height: 600,
        showDayView: false,
        showMonthView: false,
        showWeekView: true,
        weekText: 'Расписание',
        activeItem: 1,
        calendarStore: new Ext.data.JsonStore({
            storeId: 'teacherCalendarStore',
            root: 'calendars',
            idProperty: 'id',
            data: {
                "calendars":[{
                    "id":2,
                    "title":"Занятия"
                }]
            },
            proxy: new Ext.data.MemoryProxy(),
            autoLoad: true,
            fields: [
                {name:'CalendarId', mapping: 'id', type: 'int'},
                {name:'Title', mapping: 'title', type: 'string'}
            ],
            sortInfo: {
                field: 'CalendarId',
                direction: 'ASC'
            }
        }),
        eventStore: scheduleStore,
        listeners: {
            rangeselect: function(calendarObj, dates) {
                if (intensiveId != 0) {
                    var lessonAttributesWnd = makeLessonAttributesWindow(0, intensiveId, chairId, 'Добавление нового занятия', dates.StartDate, dates.EndDate, function(form, action){
                        refreshCalendar();
                    });
                    lessonAttributesWnd.show();
                } else {
                    Ext.Msg.show({
                        title: 'Нет выбранного интенсива',
                        msg: 'Чтобы добавить занятие, сперва необходимо выбрать интенсив',
                        buttons: Ext.MessageBox.OK,
                        icon: Ext.MessageBox.WARNING
                    });
                }
            },
            eventclick: function(calendarObj, rec, el) {
                if (rec.data.CalendarId == 1) {
                    var menu = new Ext.menu.Menu({
                        items: [{
                            text: 'Состав слушателей',
                            handler: function() {
                                var staffWnd = makeListenersLessonStaffWindow(rec.id);
                                staffWnd.show();
                            }
                        },{
                            text: 'Отметка посещаемости занятия',
                            handler: function() {
                                var presencesLessonWnd = makeLessonPresenceWindow(rec.id);
                                presencesLessonWnd.show();
                            }
                        },{
                            text: 'Дублировать занятие',
                            handler: function() {
                                var duplicateWnd = makeDuplicateEventWindow('Дублирование занятия', function(period, repeatCount) {
                                    Ext.Ajax.request({
                                        url: '/json/duplicatelesson/',
                                        method: 'POST',
                                        params: {
                                            lid: rec.id,
                                            period: period,
                                            repeat_count: repeatCount
                                        },
                                        success: function(response, opts) {
                                            refreshCalendar();
                                        },
                                        failure: function(response, opts) {
                                            Ext.Msg.show({
                                                title: 'Ошибка при дублировании занятия',
                                                msg: 'Не удалось продублировать занятие',
                                                buttons: Ext.MessageBox.OK,
                                                icon: Ext.MessageBox.ERROR
                                            });
                                        }
                                    });
                                });
                                duplicateWnd.show();
                            }
                        },
                        '-',
                        {
                            text: 'Редактировать занятие',
                            handler: function() {
                                var lessonAttributesWnd = makeLessonAttributesWindow(rec.id, intensiveId, chairId, 'Редактирование занятия', null, null, function(form, action){
                                    refreshCalendar();
                                });
                                lessonAttributesWnd.show();
                            }
                        },{
                            text: 'Удалить занятие',
                            handler: function() {
                                Ext.Msg.confirm('Удаление занятия', 'Вы точно хотите удалить занятие ?', function(btn){
                                    if(btn == 'yes') {
                                        Ext.Ajax.request({
                                            url: '/json/deletelesson/',
                                            method: 'POST',
                                            params: {lid: rec.id},
                                            success: function(response, opts) {
                                                refreshCalendar();
                                            },
                                            failure: function(response, opts) {
                                                Ext.Msg.show({
                                                    title: 'Ошибка при удалении',
                                                    msg: 'Не удалось удалить занятие',
                                                    buttons: Ext.MessageBox.OK,
                                                    icon: Ext.MessageBox.ERROR
                                                });
                                            }
                                        });
                                    }
                                });
                            }
                        }]
                    });
                    menu.showAt(Ext.EventObject.getXY());
                }
            }
        }
    });
    
    var scheduleWindow = new Ext.Window({
        title: 'Расписание: ' + teacherData.surname + ' ' + teacherData.name + ' ' + teacherData.patronymic,
        modal: true,
        layout: 'anchor',
        width: 800,
        items: [
            scheduleCalendar
        ],
        buttons: [{
            text: 'Закрыть',
            handler: function() {
                scheduleWindow.close();
            }
        }]
    });
    
    return scheduleWindow;
}

function makeTeacherAttributesWindow(teacherId, chairId, windowTitle, gridStore) {
    var teacherIdField = new Ext.form.Hidden({
        id: 'teacher-id',
        name: 'id',
        value: teacherId
    });
    var chairIdField = new Ext.form.Hidden({
        id: 'chair_id',
        value: chairId
    });
    var surnameField = new Ext.form.TextField({
        id: 'surname',
        fieldLabel: 'Фамилия',
        allowBlank: false,
        anchor: '100%'
    });
    var nameField = new Ext.form.TextField({
        id: 'name',
        fieldLabel: 'Имя',
        allowBlank: false,
        anchor: '100%'
    });
    var patronymicField = new Ext.form.TextField({
        id: 'patronymic',
        fieldLabel: 'Отчество',
        allowBlank: false,
        anchor: '100%'
    });
    var rankField = new Ext.form.TextField({
        id: 'rank',
        fieldLabel: 'Должность/звание',
        anchor: '100%'
    });
    var attNumField = new Ext.form.TextField({
        id: 'att_num',
        fieldLabel: '№ атт. ВАК',
        anchor: '100%'
    });
    var diplomNumField = new Ext.form.TextField({
        id: 'diplom_num',
        fieldLabel: '№ диплома',
        anchor: '100%'
    });
    var loginField = new Ext.form.TextField({
        id: 'login',
        fieldLabel: 'Логин',
        allowBlank: false,
        anchor: '100%'
    });
    var passwordField = new Ext.form.TextField({
        id: 'password',
        fieldLabel: 'Пароль',
        allowBlank: teacherId == 0 ? false : true,
        anchor: '100%'
    });

    var attributesForm = new Ext.form.FormPanel({
        id: 'teacher-attributes',
        padding: 5,
        url: '/json/saveteacherdata/',
        items: [
            teacherIdField,
            chairIdField,
            surnameField,
            nameField,
            patronymicField,
            rankField,
            attNumField,
            diplomNumField,
            loginField,
            passwordField
        ],
        buttons: [{
            text: 'Сохранить',
            plugins: 'defaultButton',
            handler: function() {
                var form = attributesForm.getForm();
                if (form.isValid()) {
                    form.submit({
                        waitMsg: 'Сохранение данных о преподавателе',
                        success: function(form, action) {
                            if (gridStore != null) {
                                gridStore.load();
                            }
                            teacherAttributes.close();
                        },
                        failure: function(form, action) {
                            Ext.Msg.show({
                                title: 'Ошибка при сохранении',
                                msg: action.result.error_message,
                                buttons: Ext.MessageBox.OK,
                                icon: Ext.MessageBox.WARNING
                            });
                        }
                    })
                } else {
                    Ext.Msg.show({
                        title: 'Ошибка при валидации',
                        msg: 'В форму внесены некорректные данные',
                        buttons: Ext.MessageBox.OK,
                        icon: Ext.MessageBox.WARNING
                    });
                }
            }
        },{
            text: 'Отмена',
            handler: function() {
                teacherAttributes.close();
            }
        }]
    });

    var attributesStore = new Ext.data.Store({
        reader: new Ext.data.JsonReader({
            fields: [
                'id',
                'surname',
                'name',
                'patronymic',
                'rank',
                'att_num',
                'diplom_num',
                'login',
                'password'
            ],
            root: 'teacherdata'
        }),
        proxy: new Ext.data.HttpProxy({
            url: '/json/getteacherdata/?tid=' + teacherId
        }),
        listeners: {
            'load': function() {
                var rec = this.getAt(0);
                surnameField.setValue(rec.data.surname);
                nameField.setValue(rec.data.name);
                patronymicField.setValue(rec.data.patronymic);
                loginField.setValue(rec.data.login);
                rankField.setValue(rec.data.rank);
                attNumField.setValue(rec.data.att_num);
                diplomNumField.setValue(rec.data.diplom_num);
            }
        }
    });

    var teacherAttributes = new Ext.Window({
        title: windowTitle,
        modal: true,
        width: 483,
        items: [
            attributesForm
        ]
    });

    if(teacherId != 0) {
        teacherAttributes.on('show', function(){
            attributesStore.load();
        });
    }

    return teacherAttributes;
}

function makeTeacherLessonGridWindow(teacherData) {
    var lessonsStore = new Ext.data.Store({
        autoLoad: true,
        reader: new Ext.data.JsonReader({
            fields: [
                'id',
                'start',
                'theme',
                'auditory',
                'intensive',
                'type'
            ],
            root: 'lessons'
        }),
        proxy: new Ext.data.HttpProxy({
            url: '/json/getteacherlessons/?tid=' + teacherData.id
        })
    });
    
    var lessonsGrid = new Ext.grid.GridPanel({
        store: lessonsStore,
        anchor: '100%, 100%',
        height: 400,
        loadMask: true,
        sm: new Ext.grid.RowSelectionModel({singleSelect:true}),
        columns: [
            {header: 'Дата начала', dataIndex: 'start', sortable: true, width: 120},
            {header: 'Курс', dataIndex: 'intensive', sortable: true, width: 200},
            {header: 'Тема', dataIndex: 'theme', sortable: true, width: 200},
            {header: 'Аудитория', dataIndex: 'auditory', sortable: true, width: 100},
            {header: 'Тип занятия', dataIndex: 'type', sortable: true, width: 120, renderer: function(value) {
                    switch (value) {
                        case 1:
                            return 'Практическое';
                        case 2:
                            return 'Лекционно-практическое';
                    }
                    return 'Теоретическое';
            }}
        ]
    });
    
    var lessonsGridWindow = new Ext.Window({
        title: 'Назначенные занятия: ' + teacherData.surname + ' ' + teacherData.name + ' ' + teacherData.patronymic,
        modal: true,
        layout: 'anchor',
        width: 800,
        items: [
            lessonsGrid
        ],
        buttons: [{
            text: 'Закрыть',
            handler: function() {
                lessonsGridWindow.close();
            }
        }]
    });
    
    return lessonsGridWindow;
}

function makeGenerateTeacherContractWindow(teacherData) {
    var teacherIdField = new Ext.form.Hidden({
        id: 'teacher_id',
        value: teacherData.id
    });
    var startField = new Ext.form.DateField({
        id: 'start',
        fieldLabel: 'С',
        format: 'Y-m-d',
        allowBlank: false,
        value: Ext.state.Manager.get('contractStartDate'),
        anchor: '100%',
        vtype: 'daterange',
        endDateField: 'end'
    });
    var endField = new Ext.form.DateField({
        id: 'end',
        fieldLabel: 'По',
        format: 'Y-m-d',
        allowBlank: false,
        value: Ext.state.Manager.get('contractEndDate'),
        anchor: '100%',
        vtype: 'daterange',
        startDateField: 'start'
    });
    var semesterField = new Ext.form.ComboBox({
        id: 'semester_name',
        hiddenName: 'semester',
        fieldLabel: 'Семестр',
        mode: 'local',
        store: new Ext.data.ArrayStore({
            id: 0,
            fields: [
                'id',
                'semesterText'
            ],
            data: [[1, '1 семестр'], [2, '2 семестр']]
        }),
        valueField: 'id',
        displayField: 'semesterText',
        value: 1,
        triggerAction: 'all',
        allowBlank: false,
        anchor: '100%'        
    });
    var makeDateField = new Ext.form.DateField({
        id: 'make_date',
        fieldLabel: 'Дата оформления',
        format: 'Y-m-d',
        value: new Date(),
        allowBlank: false,
        anchor: '100%'
    });
    var hourCostField = new Ext.form.NumberField({
        id: 'hour_cost',
        fieldLabel: 'Оплата за один час',
        allowBlank: false,
        minValue: 0,
        anchor: '100%'
    });

    var contractForm = new Ext.form.FormPanel({
        id: 'teacher-contract-attributes',
        padding: 5,
        url: '/print/teachercontract/',
        items: [
            teacherIdField,
            startField,
            endField,
            semesterField,
            makeDateField,
            hourCostField
        ],
        buttons: [{
            text: 'Сформировать',
            plugins: 'defaultButton',
            handler: function() {
                var form = contractForm.getForm();
                if(form.isValid()) {
                    form.submit();
                    contractAttributes.close();
                } else {
                    Ext.Msg.show({
                        title: 'Ошибка при валидации',
                        msg: 'В форму внесены некорректные данные',
                        buttons: Ext.MessageBox.OK,
                        icon: Ext.MessageBox.WARNING
                    });
                }
            }
        },{
            text: 'Отмена',
            handler: function() {
                contractAttributes.close();
            }
        }]
    });
    contractForm.getForm().standardSubmit = true;

    var contractAttributes = new Ext.Window({
        title: 'Формирование трудового договора на выполнение учебной работы',
        modal: true,
        layout: 'anchor',
        width: 400,
        items: [
            contractForm
        ]
    });
    
    return contractAttributes;
}

function makeGenerateTeacherReportWindow(teacherData) {
    var teacherIdField = new Ext.form.Hidden({
        id: 'teacher_id',
        value: teacherData.id
    });
    var startField = new Ext.form.DateField({
        id: 'start',
        fieldLabel: 'С',
        format: 'Y-m-d',
        allowBlank: false,
        value: Ext.state.Manager.get('contractStartDate'),
        anchor: '100%',
        vtype: 'daterange',
        endDateField: 'end'
    });
    var endField = new Ext.form.DateField({
        id: 'end',
        fieldLabel: 'По',
        format: 'Y-m-d',
        allowBlank: false,
        value: Ext.state.Manager.get('contractEndDate'),
        anchor: '100%',
        vtype: 'daterange',
        startDateField: 'start'
    });
    var contractMakeDateField = new Ext.form.DateField({
        id: 'contract_make_date',
        fieldLabel: 'Дата оформления договора',
        format: 'Y-m-d',
        value: new Date(),
        allowBlank: false,
        anchor: '100%'
    });
    var makeDateField = new Ext.form.DateField({
        id: 'make_date',
        fieldLabel: 'Дата составления отчёта',
        format: 'Y-m-d',
        value: new Date(),
        allowBlank: false,
        anchor: '100%'
    });
    var hourCostField = new Ext.form.NumberField({
        id: 'hour_cost',
        fieldLabel: 'Оплата за один час',
        allowBlank: false,
        minValue: 0,
        anchor: '100%'
    });

    var reportForm = new Ext.form.FormPanel({
        id: 'teacher-report-attributes',
        padding: 5,
        url: '/print/teacherreport/',
        items: [
            teacherIdField,
            startField,
            endField,
            contractMakeDateField,
            makeDateField,
            hourCostField
        ],
        buttons: [{
            text: 'Сформировать',
            plugins: 'defaultButton',
            handler: function() {
                
            }
        },{
            text: 'Отмена',
            handler: function() {
                reportAttributes.close();
            }
        }]
    });

    var reportAttributes = new Ext.Window({
        title: 'Сформировать отчёт о выполнении учебной работы',
        modal: true,
        layout: 'anchor',
        width: 400,
        items: [
            reportForm
        ]
    });
    
    return reportAttributes;
}

function makeAuditoriesGridWindow(chairId) {
    var auditoriesStore = new Ext.data.Store({
        autoLoad: true,
        reader: new Ext.data.JsonReader({
            fields: [
                'id',
                'surname',
                'name',
                'patronymic'
            ],
            root: 'auditories'
        }),
        proxy: new Ext.data.HttpProxy({
            url: '/json/getauditoriesforgrid/'
        })
    });

    var auditoriesGrid = new Ext.grid.GridPanel({
        store: auditoriesStore,
        anchor: '100%, 100%',
        height: 400,
        loadMask: true,
        sm: new Ext.grid.RowSelectionModel({singleSelect:true}),
        columns: [
            {header: 'Наименование аудитории', dataIndex: 'name', sortable: true, width: 400},
            {
                xtype: 'actioncolumn',
                width: 40,
                header: 'Операции',
                items: [{
                    icon: '/images/icons/edit.gif',
                    tooltip: 'Редактировать',
                    handler: function(gridObj, rowIndex, colIndex) {
                        var rec = gridObj.getStore().getAt(rowIndex);
                        var auditoryAttributes = makeAuditoryAttributesWindow(rec.data.id, chairId, 'Редактирование аудитории', auditoriesStore);
                        auditoryAttributes.show();
                    }
                },{
                    icon: '/images/icons/delete.gif',
                    tooltip: 'Удалить',
                    handler: function(gridObj, rowIndex, colIndex) {
                        var rec = gridObj.getStore().getAt(rowIndex);
                        Ext.Msg.confirm('Удаление аудитории', 'Удалить аудиторию "' + rec.data.name + '" ?', function(btn){
                            if(btn == 'yes') {
                                Ext.Ajax.request({
                                    url: '/json/deleteauditory/',
                                    method: 'POST',
                                    params: {aid: rec.data.id},
                                    success: function(response, opts) {
                                        auditoriesStore.load();
                                    },
                                    failure: function(response, opts) {
                                        Ext.Msg.show({
                                            title: 'Ошибка при удалении',
                                            msg: 'Не удалось удалить аудиторию',
                                            buttons: Ext.MessageBox.OK,
                                            icon: Ext.MessageBox.ERROR
                                        });
                                    }
                                });
                            }
                        });
                    }
                }]
            }
        ]
    });

    var auditoriesGridWindow = new Ext.Window({
        title: 'Список аудиторий',
        modal: true,
        layout: 'anchor',
        width: 660,
        items: [
            auditoriesGrid
        ],
        buttons: [{
            text: 'Добавить новую аудиторию',
            handler: function() {
                var auditoryAttributes = makeAuditoryAttributesWindow(0, chairId, 'Добавление новой аудитории', auditoriesStore);
                auditoryAttributes.show();
            }
        },{
            text: 'Закрыть',
            handler: function() {
                auditoriesGridWindow.close();
            }
        }]
    });
    
    return auditoriesGridWindow;
}

function makeAuditoryAttributesWindow(auditoryId, chairId, windowTitle, gridStore) {
    var auditoryIdField = new Ext.form.Hidden({
        id: 'auditory-id',
        name: 'id',
        value: auditoryId
    });
    var nameField = new Ext.form.TextField({
        id: 'name',
        fieldLabel: 'Наименование',
        allowBlank: false,
        anchor: '100%'
    });

    var attributesForm = new Ext.form.FormPanel({
        id: 'auditory-attributes',
        padding: 5,
        url: '/json/saveauditorydata/',
        items: [
            auditoryIdField,
            nameField
        ],
        buttons: [{
            text: 'Сохранить',
            plugins: 'defaultButton',
            handler: function() {
                var form = attributesForm.getForm();
                if (form.isValid()) {
                    form.submit({
                        waitMsg: 'Сохранение данных об аудитории',
                        success: function(form, action) {
                            if (gridStore != null) {
                                gridStore.load();
                            }
                            auditoryAttributes.close();
                        },
                        failure: function(form, action) {
                            Ext.Msg.show({
                                title: 'Ошибка при сохранении',
                                msg: action.result.error_message,
                                buttons: Ext.MessageBox.OK,
                                icon: Ext.MessageBox.WARNING
                            });
                        }
                    })
                } else {
                    Ext.Msg.show({
                        title: 'Ошибка при валидации',
                        msg: 'В форму внесены некорректные данные',
                        buttons: Ext.MessageBox.OK,
                        icon: Ext.MessageBox.WARNING
                    });
                }
            }
        },{
            text: 'Отмена',
            handler: function() {
                auditoryAttributes.close();
            }
        }]
    });

    var attributesStore = new Ext.data.Store({
        reader: new Ext.data.JsonReader({
            fields: [
                'id',
                'name'
            ],
            root: 'auditorydata'
        }),
        proxy: new Ext.data.HttpProxy({
            url: '/json/getauditorydata/?aid=' + auditoryId
        }),
        listeners: {
            'load': function() {
                var rec = this.getAt(0);
                nameField.setValue(rec.data.name);
            }
        }
    });

    var auditoryAttributes = new Ext.Window({
        title: windowTitle,
        modal: true,
        width: 483,
        items: [
            attributesForm
        ]
    });

    if(auditoryId != 0) {
        auditoryAttributes.on('show', function(){
            attributesStore.load();
        });
    }

    return auditoryAttributes;
}

function makeLessonAttributesWindow(lessonId, intensiveId, chairId, windowTitle, startTime, endTime, onSuccess) {
    var lessonIdField = new Ext.form.Hidden({
        id: 'lesson-id',
        name: 'id',
        value: lessonId
    });
    var intensiveIdField = new Ext.form.Hidden({
        id: 'intensive_id',
        value: intensiveId
    });
    var startField = new Ext.form.Hidden({
        id: 'start',
        allowBlank: false
    });
    var startTimeField = new Ext.form.TimeField({
        id: 'start_time',
        fieldLabel: 'Время начала',
        submitValue: false,
        allowBlank: false,
        value: startTime,
        anchor: '100%',
        increment: 10,
        format: 'H:i'
    });
    var endField = new Ext.form.Hidden({
        id: 'end',
        allowBlank: false
    });
    var endTimeField = new Ext.form.TimeField({
        id: 'end_time',
        fieldLabel: 'Время окончания',
        submitValue: false,
        allowBlank: false,
        value: endTime,
        anchor: '100%',
        increment: 10,
        format: 'H:i'
    });
    var themeField = new Ext.form.TextField({
        id: 'theme',
        fieldLabel: 'Тема занятия',
        allowBlank: false,
        anchor: '100%'
    });
    var teacherIdField = new Ext.form.Hidden({
        id: 'teacher_id',
        allowBlank: false
    });
    var teacherField = new Ext.form.TriggerField({
        id: 'teacher',
        fieldLabel: 'Преподаватель',
        editable: false,
        submitValue: false,
        allowBlank: false,
        anchor: '100%'
    });
    teacherField.onTriggerClick = function(ev) {
        var teacherSelect = makeTeacherSelectWindow(chairId, this, teacherIdField);
        teacherSelect.show();
    }
    var auditoryIdField = new Ext.form.Hidden({
        id: 'auditory_id',
        allowBlank: false
    });
    var auditoryField = new Ext.form.TriggerField({
        id: 'auditory',
        fieldLabel: 'Аудитория',
        editable: false,
        submitValue: false,
        allowBlank: false,
        anchor: '100%'
    });
    auditoryField.onTriggerClick = function(ev) {
        var auditorySelect = makeAuditorySelectWindow(chairId, this, auditoryIdField);
        auditorySelect.show();
    }
    var statusField = new Ext.form.ComboBox({
        id: 'status_name',
        hiddenName: 'status',
        fieldLabel: 'Статус',
        mode: 'local',
        store: new Ext.data.ArrayStore({
            id: 0,
            fields: [
                'id',
                'statusText'
            ],
            data: [[0, 'Черновик'], [1, 'Утверждено'], [2, 'Проведено']]
        }),
        valueField: 'id',
        displayField: 'statusText',
        value: 0,
        triggerAction: 'all',
        allowBlank: false,
        anchor: '100%'
    });
    var typeField = new Ext.form.ComboBox({
        id: 'type_name',
        hiddenName: 'type',
        fieldLabel: 'Тип занятия',
        mode: 'local',
        store: new Ext.data.ArrayStore({
            id: 0,
            fields: [
                'id',
                'statusText'
            ],
            data: [[0, 'Теоретическое'], [1, 'Практическое'], [2, 'Лекционно-практическое']]
        }),
        valueField: 'id',
        displayField: 'statusText',
        value: 0,
        triggerAction: 'all',
        allowBlank: false,
        anchor: '100%'
    });

    var attributesStore = new Ext.data.Store({
        reader: new Ext.data.JsonReader({
            fields: [
                'id',
                'intensive_id',
                'start',
                'end',
                'theme',
                'teacher_id',
                'auditory_id',
                'status',
                'type'
            ],
            root: 'lessondata'
        }),
        proxy: new Ext.data.HttpProxy({
            url: '/json/getlessondata/?lid=' + lessonId
        }),
        listeners: {
            'load': function() {
                var rec = this.getAt(0);
                lessonIdField.setValue(rec.data.id);
                intensiveIdField.setValue(rec.data.intensive_id);
                startField.setValue(rec.data.start);
                endField.setValue(rec.data.end);
                themeField.setValue(rec.data.theme);
                teacherIdField.setValue(rec.data.teacher_id);
                auditoryIdField.setValue(rec.data.auditory_id);
                statusField.setValue(rec.data.status);
                typeField.setValue(rec.data.type);
                
                startTime = Date.parseDate(rec.data.start, "Y-m-d H:i:s");
                startTimeField.setValue(startTime);
                endTime = Date.parseDate(rec.data.end, "Y-m-d H:i:s");
                endTimeField.setValue(endTime);
                
                new Ext.data.Store({
                    autoLoad: true,
                    reader: new Ext.data.JsonReader({
                        fields: [
                            'id',
                            'surname',
                            'name',
                            'patronymic',
                            'login',
                            'password'
                        ],
                        root: 'teacherdata'
                    }),
                    proxy: new Ext.data.HttpProxy({
                        url: '/json/getteacherdata/?tid=' + rec.data.teacher_id
                    }),
                    listeners: {
                        'load': function() {
                            var teacherData = this.getAt(0);
                            teacherField.setValue(teacherData.data.surname + ' ' + teacherData.data.name + ' ' + teacherData.data.patronymic);
                        }
                    }
                });
                
                new Ext.data.Store({
                    autoLoad: true,
                    reader: new Ext.data.JsonReader({
                        fields: [
                            'id',
                            'name'
                        ],
                        root: 'auditorydata'
                    }),
                    proxy: new Ext.data.HttpProxy({
                        url: '/json/getauditorydata/?aid=' + rec.data.auditory_id
                    }),
                    listeners: {
                        'load': function() {
                            var rec = this.getAt(0);
                            auditoryField.setValue(rec.data.name);
                        }
                    }
                });
            }
        }
    });

    var attributesForm = new Ext.form.FormPanel({
        id: 'lesson-attributes',
        padding: 5,
        url: '/json/savelessondata/',
        items: [
            lessonIdField,
            intensiveIdField,
            startField,
            startTimeField,
            endField,
            endTimeField,
            themeField,
            teacherIdField,
            teacherField,
            auditoryIdField,
            auditoryField,
            statusField,
            typeField
        ],
        buttons: [{
            text: 'Сохранить',
            plugins: 'defaultButton',
            handler: function() {
                var form = attributesForm.getForm();
                if(form.isValid()) {
                    var startDate = startTime.getFullYear();
                    startDate += '-';
                    var startMonth = startTime.getMonth() + 1;
                    startDate += (startMonth < 10) ? '0' + startMonth : startMonth;
                    startDate += '-';
                    var startDay = startTime.getDate();
                    startDate += (startDay < 10) ? '0' + startDay : startDay;

                    var endDate = endTime.getFullYear();
                    endDate += '-';
                    var endMonth = endTime.getMonth() + 1;
                    endDate += (endMonth < 10) ? '0' + endMonth : endMonth;
                    endDate += '-';
                    var endDay = endTime.getDate();
                    endDate += (endDay < 10) ? '0' + endDay : endDay;

                    form.items.item('start').setValue(startDate + ' ' + form.items.item('start_time').value);
                    form.items.item('end').setValue(endDate + ' ' + form.items.item('end_time').value);
                    form.submit({
                        waitMsg: 'Сохранение данных о занятии',
                        success: function(form, action) {
                            onSuccess(form, action);
                            lessonAttributes.close();
                        },
                        failure: function(form, action) {
                            Ext.Msg.show({
                                title: 'Ошибка при сохранении',
                                msg: action.result.error_message,
                                buttons: Ext.MessageBox.OK,
                                icon: Ext.MessageBox.WARNING
                            });
                        }
                    });
                } else {
                    Ext.Msg.show({
                        title: 'Ошибка при валидации',
                        msg: 'В форму внесены некорректные данные',
                        buttons: Ext.MessageBox.OK,
                        icon: Ext.MessageBox.WARNING
                    });
                }
            }
        },{
            text: 'Отмена',
            handler: function() {
                lessonAttributes.close();
            }
        }]
    });

    var lessonAttributes = new Ext.Window({
        title: windowTitle,
        modal: true,
        width: 600,
        items: [
            attributesForm
        ]
    });

    if(lessonId != 0) {
        lessonAttributes.on('show', function(){
            attributesStore.load();
        });
    }

    return lessonAttributes;
}

function makeTeacherSelectWindow(chairId, teacherField, teacherIdField)
{
    var teachersStore = new Ext.data.Store({
        autoLoad: true,
        reader: new Ext.data.JsonReader({
            fields: [
                'id',
                'surname',
                'name',
                'patronymic'
            ],
            root: 'teachers'
        }),
        proxy: new Ext.data.HttpProxy({
            url: '/json/getteachersforgrid/'
        })
    });

    var teachersGrid = new Ext.grid.GridPanel({
        store: teachersStore,
        anchor: '100%, 100%',
        height: 400,
        loadMask: true,
        sm: new Ext.grid.RowSelectionModel({singleSelect:true}),
        columns: [
            {header: 'Фамилия', dataIndex: 'surname', sortable: true, width: 150},
            {header: 'Имя', dataIndex: 'name', sortable: true, width: 150},
            {header: 'Отчество', dataIndex: 'patronymic', sortable: true, width: 150}
        ]
    });
    teachersGrid.on('rowdblclick', function(gridObj, rowIndex, e) {
        var rec = gridObj.getStore().getAt(rowIndex);
        teacherField.setValue(rec.data.surname + ' ' + rec.data.name + ' ' + rec.data.patronymic);
        teacherIdField.setValue(rec.data.id);
        teacherSelectWnd.close();
    });

    var teacherSelectWnd =  new Ext.Window({
        title: 'Выбор преподавателя',
        modal: true,
        layout: 'anchor',
        width: 470,
        items: [
            teachersGrid
        ],
        buttons: [{
            text: 'Добавить нового преподавателя',
            handler: function() {
                var teacherAttributes = makeTeacherAttributesWindow(0, chairId, 'Добавление нового преподавателя', teachersStore);
                teacherAttributes.show();
            }
        },{
            text: 'Выбрать',
            handler: function() {
                var rec = teachersGrid.getSelectionModel().getSelected();
                teacherField.setValue(rec.data.surname + ' ' + rec.data.name + ' ' + rec.data.patronymic);
                teacherIdField.setValue(rec.data.id);
                teacherSelectWnd.close();
            }
        }]
    });

    return teacherSelectWnd;
}

function makeAuditorySelectWindow(chairId, auditoryField, auditoryIdField) {
    var auditoriesStore = new Ext.data.Store({
        autoLoad: true,
        reader: new Ext.data.JsonReader({
            fields: [
                'id',
                'name',
            ],
            root: 'auditories'
        }),
        proxy: new Ext.data.HttpProxy({
            url: '/json/getauditoriesforgrid/'
        })
    });

    var auditoriesGrid = new Ext.grid.GridPanel({
        store: auditoriesStore,
        anchor: '100%, 100%',
        height: 400,
        loadMask: true,
        sm: new Ext.grid.RowSelectionModel({singleSelect:true}),
        columns: [
            {header: 'Наименование', dataIndex: 'name', sortable: true, width: 350},
        ]
    });
    auditoriesGrid.on('rowdblclick', function(gridObj, rowIndex, e) {
        var rec = gridObj.getStore().getAt(rowIndex);
        auditoryField.setValue(rec.data.name);
        auditoryIdField.setValue(rec.data.id);
        auditorySelectWnd.close();
    });

    var auditorySelectWnd =  new Ext.Window({
        title: 'Выбор аудитории',
        modal: true,
        layout: 'anchor',
        width: 470,
        items: [
            auditoriesGrid
        ],
        buttons: [{
            text: 'Добавить новую аудиторию',
            handler: function() {
                var auditoryAttributes = makeAuditoryAttributesWindow(0, chairId, 'Добавление новой аудитории', auditoriesStore);
                auditoryAttributes.show();
            }
        },{
            text: 'Выбрать',
            handler: function() {
                var rec = auditoriesGrid.getSelectionModel().getSelected();
                auditoryField.setValue(rec.data.name);
                auditoryIdField.setValue(rec.data.id);
                auditorySelectWnd.close();
            }
        }]
    });

    return auditorySelectWnd;
}

function makeListenersLessonStaffWindow(lessonId) {
    var staffStore = new Ext.data.Store({
        autoLoad: true,
        reader: new Ext.data.JsonReader({
            fields: [
                'listener_id',
                'surname',
                'name',
                'patronymic',
                'group'
            ],
            root: 'presences'
        }),
        proxy: new Ext.data.HttpProxy({
            url: '/json/getlessonpresence/?lid=' + lessonId
        })
    });

    var staffGrid = new Ext.grid.GridPanel({
        store: staffStore,
        anchor: '100%, 100%',
        height: 400,
        loadMask: true,
        sm: new Ext.grid.RowSelectionModel({singleSelect:true}),
        columns: [
            {header: 'Фамилия', dataIndex: 'surname', sortable: true, width: 100},
            {header: 'Имя', dataIndex: 'name', sortable: true, width: 100},
            {header: 'Отчество', dataIndex: 'patronymic', sortable: true, width: 100},
            {header: 'Группа', dataIndex: 'group', sortable: true},
            {
                xtype: 'actioncolumn',
                width: 26,
                header: 'Операции',
                items: [{
                    icon: '/images/icons/delete.gif',
                    tooltip: 'Удалить',
                    handler: function(gridObj, rowIndex, colIndex) {
                        var rec = gridObj.getStore().getAt(rowIndex);
                        Ext.Msg.confirm('Удаление слушателя с занятия', 'Удалить слушателя "' + rec.data.surname + ' ' + rec.data.name + ' ' + rec.data.patronymic + '" с занятия ?', function(btn){
                            if(btn == 'yes') {
                                Ext.Ajax.request({
                                    url: '/json/deletelistenerfromlesson/',
                                    method: 'POST',
                                    params: {
                                        listener_id: rec.data.listener_id,
                                        lesson_id: lessonId
                                    },
                                    success: function(response, opts) {
                                        staffStore.load();
                                    },
                                    failure: function(response, opts) {
                                        Ext.Msg.show({
                                            title: 'Ошибка при удалении',
                                            msg: 'Не удалось удалить слушателя с занятия',
                                            buttons: Ext.MessageBox.OK,
                                            icon: Ext.MessageBox.ERROR
                                        });
                                    }
                                });
                            }
                        });
                    }
                }]
            }
        ]
    });

    var staffWnd =  new Ext.Window({
        title: 'Состав слушателей',
        modal: true,
        layout: 'anchor',
        width: 470,
        items: [
            staffGrid
        ],
        buttons: [{
            text: 'Добавить слушателя на занятие',
            handler: function() {
                var addListenerOnLesson = makeListenerToLessonWindow(lessonId, staffStore);
                addListenerOnLesson.show();
            }
        },{
            text: 'Закрыть',
            handler: function() {
                staffWnd.close();
            }
        }]
    });

    return staffWnd;
}

function makeListenerToLessonWindow(lessonId, staffStore) {
    var listenersStore = new Ext.data.Store({
        autoLoad: true,
        reader: new Ext.data.JsonReader({
            fields: [
                'id',
                'listener_id',
                'surname',
                'name',
                'patronymic',
                'group',
                'themes'
            ],
            root: 'listeners'
        }),
        proxy: new Ext.data.HttpProxy({
            url: '/json/getlistenersforaddingtolesson/?lid=' + lessonId
        })
    });

    var listenersGrid = new Ext.grid.GridPanel({
        id: 'addlistener-grid',
        store: listenersStore,
        anchor: '100%, 100%',
        height: 400,
        loadMask: true,
        sm: new Ext.grid.RowSelectionModel({singleSelect:true}),
        columns: [
            {header: 'Фамилия', dataIndex: 'surname', sortable: true, width: 100},
            {header: 'Имя', dataIndex: 'name', sortable: true, width: 100},
            {header: 'Отчество', dataIndex: 'patronymic', sortable: true, width: 100},
            {header: 'Группа', dataIndex: 'group', sortable: true, width: 75},
            {header: 'Желаемые темы', dataIndex: 'themes', sortable: true, width: 200}
        ]
    });

    function addListenerToLesson() {
        var rec = listenersGrid.getSelectionModel().getSelected();
        Ext.Ajax.request({
            url: '/json/addlistenertolesson/',
            method: 'POST',
            params: {
                lesson_id:      lessonId,
                listener_id:    rec.data.id
            },
            success: function(response, opts) {
                staffStore.load();
                listenersWnd.close();
            },
            failure: function(response, opts) {
                Ext.Msg.show({
                    title: 'Ошибка при добавлении слушателя на занятие',
                    msg: 'Не удалось произвести добавление слушателя на занятие',
                    buttons: Ext.MessageBox.OK,
                    icon: Ext.MessageBox.ERROR
                });
            }
        });
    }
    listenersGrid.on('rowdblclick', function(gridObj, rowIndex, e) {
        addListenerToLesson();
    });

    var listenersWnd =  new Ext.Window({
        title: 'Запись слушателя на занятие',
        modal: true,
        layout: 'anchor',
        width: 600,
        items: [
            listenersGrid
        ],
        buttons: [{
            text: 'Добавить',
            handler: function() {
                addListenerToLesson();
            }
        },{
            text: 'Отмена',
            handler: function() {
                listenersWnd.close();
            }
        }]
    });

    return listenersWnd;
}

function makeLessonPresenceWindow(lessonId) {
    var presencesStore = new Ext.data.Store({
        autoLoad: true,
        reader: new Ext.data.JsonReader({
            fields: [
                'listener_id',
                'surname',
                'name',
                'patronymic',
                'group',
                {name: 'presented', type: 'bool'}
            ],
            root: 'presences'
        }),
        proxy: new Ext.data.HttpProxy({
            url: '/json/getlessonpresence/?lid=' + lessonId
        })
    });

    var presencesGrid = new Ext.grid.GridPanel({
        store: presencesStore,
        anchor: '100%, 100%',
        height: 400,
        loadMask: true,
        sm: new Ext.grid.RowSelectionModel({singleSelect:true}),
        columns: [
            {header: 'Фамилия', dataIndex: 'surname', sortable: true, width: 100},
            {header: 'Имя', dataIndex: 'name', sortable: true, width: 100},
            {header: 'Отчество', dataIndex: 'patronymic', sortable: true, width: 100},
            {header: 'Группа', dataIndex: 'group', sortable: true, width: 75},
            {header: 'Присутствовал', dataIndex: 'presented', sortable: true, width: 50, xtype: 'checkcolumn'}
        ]
    });

    var presencesWnd =  new Ext.Window({
        title: 'Отметка посещаемости занятия',
        modal: true,
        layout: 'anchor',
        width: 470,
        items: [
            presencesGrid
        ],
        buttons: [{
            text: 'Сохранить',
            handler: function() {
                var presencesStates = new Array();
                presencesStore.each(function(rec){
                    presencesStates.push({
                        id:         rec.data.listener_id,
                        presented:  rec.data.presented
                    });
                });
                Ext.Ajax.request({
                    url: '/json/checklessonpresence/',
                    method: 'POST',
                    params: {
                        lid:    lessonId,
                        states: Ext.util.JSON.encode(presencesStates)
                    },
                    success: function(response, opts) {
                        Ext.Msg.show({
                            title: 'Успех при отметке посещаемости',
                            msg: 'Отметка посещений произведена успешно',
                            buttons: Ext.MessageBox.OK,
                            icon: Ext.MessageBox.INFO
                        });
                        presencesWnd.close();
                    },
                    failure: function(response, opts) {
                        Ext.Msg.show({
                            title: 'Ошибка при отметке посещений',
                            msg: 'Не удалось произвести отметку посещаемости занятия',
                            buttons: Ext.MessageBox.OK,
                            icon: Ext.MessageBox.ERROR
                        });
                    }
                });
            }
        },{
            text: 'Отмена',
            handler: function() {
                presencesWnd.close();
            }
        }]
    });

    return presencesWnd;
}

function makeAddListenerToLessonWindow(onSelect) {
    var listenersStore = new Ext.data.Store({
        autoLoad: true,
        reader: new Ext.data.JsonReader({
            fields: [
                'surname',
                'name',
                'patronymic',
                'group',
                'themes'
            ],
            root: 'listeners'
        }),
        proxy: new Ext.data.HttpProxy({
            url: '/json/getlistenersforaddingtolesson/'
        })
    });

    var listenersGrid = new Ext.grid.GridPanel({
        store: listenersStore,
        anchor: '100%, 100%',
        height: 400,
        loadMask: true,
        sm: new Ext.grid.RowSelectionModel({singleSelect:true}),
        columns: [
            {header: 'Фамилия', dataIndex: 'surname', sortable: true, width: 100},
            {header: 'Имя', dataIndex: 'name', sortable: true, width: 100},
            {header: 'Отчество', dataIndex: 'patronymic', sortable: true, width: 100},
            {header: 'Группа', dataIndex: 'group', sortable: true, width: 75},
            {header: 'Желаемые темы', dataIndex: 'themes', sortable: true, width: 200}
        ]
    });

    var listenersWnd =  new Ext.Window({
        title: 'Добавление слушателя на занятие',
        modal: true,
        layout: 'anchor',
        width: 600,
        items: [
            listenersGrid
        ],
        buttons: [{
            text: 'Выбрать',
            handler: function() {
                var rec = listenersGrid.getSelectionModel().getSelected();
                onSelect(rec);
            }
        },{
            text: 'Отмена',
            handler: function() {
                listenersWnd.close();
            }
        }]
    });

    return listenersWnd;
}

function makeDateRangeSelectWindow(windowTitle, onSubmit) {
    var startField = new Ext.form.DateField({
        id: 'start',
        fieldLabel: 'Начало',
        format: 'Y-m-d',
        allowBlank: false,
        value: Ext.state.Manager.get('contractStartDate'),
        anchor: '100%',
        vtype: 'daterange',
        endDateField: 'end'
    });
    var endField = new Ext.form.DateField({
        id: 'end',
        fieldLabel: 'Конец',
        format: 'Y-m-d',
        allowBlank: false,
        value: Ext.state.Manager.get('contractEndDate'),
        anchor: '100%',
        vtype: 'daterange',
        startDateField: 'start'
    });

    var dateRangeSelectForm = new Ext.form.FormPanel({
        padding: 5,
        items: [
            startField,
            endField
        ],
        buttons: [{
            text: 'Сформировать',
            plugins: 'defaultButton',
            handler: function() {
                var form = dateRangeSelectForm.getForm();
                if(form.isValid()) {
                    onSubmit(startField.getValue(), endField.getValue());
                } else {
                    Ext.Msg.show({
                        title: 'Ошибка при валидации',
                        msg: 'В форму внесены некорректные данные',
                        buttons: Ext.MessageBox.OK,
                        icon: Ext.MessageBox.WARNING
                    });
                }
            }
        },{
            text: 'Отмена',
            handler: function() {
                dateRangeSelectWindow.close();
            }
        }]
    });

    var dateRangeSelectWindow = new Ext.Window({
        title: windowTitle,
        modal: true,
        width: 300,
        items: [
            dateRangeSelectForm
        ]
    })

    return dateRangeSelectWindow;
}

function makeDuplicateEventWindow(windowTitle, onSubmit) {
    var periodField = new Ext.form.NumberField({
        id: 'period',
        fieldLabel: 'Период (в днях)',
        allowBlank: false,
        anchor: '100%',
        minValue: 0
    });
    var repeatCountField = new Ext.form.NumberField({
        id: 'repeat_count',
        fieldLabel: 'Количество повторений',
        allowBlank: false,
        anchor: '100%',
        minValue: 0
    });

    var duplicateForm = new Ext.form.FormPanel({
        padding: 5,
        items: [
            periodField,
            repeatCountField
        ],
        buttons: [{
            text: 'Дублировать',
            plugins: 'defaultButton',
            handler: function() {
                var form = duplicateForm.getForm();
                if(form.isValid()) {
                    onSubmit(periodField.getValue(), repeatCountField.getValue());
                    duplicateWindow.close();
                } else {
                    Ext.Msg.show({
                        title: 'Ошибка при валидации',
                        msg: 'В форму внесены некорректные данные',
                        buttons: Ext.MessageBox.OK,
                        icon: Ext.MessageBox.WARNING
                    });
                }
            }
        },{
            text: 'Отмена',
            handler: function() {
                duplicateWindow.close();
            }
        }]
    });

    var duplicateWindow = new Ext.Window({
        title: windowTitle,
        modal: true,
        width: 300,
        items: [
            duplicateForm
        ]
    })

    return duplicateWindow;
}